home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 1041 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.7 KB

  1. Path: Rezonet.net!news
  2. From: ray@ultimate-tech.com (Ray Dunn)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Problem with stringcopy
  5. Date: 11 Jan 1996 03:19:48 GMT
  6. Organization: Ultimate Technographics Inc.
  7. Distribution: world
  8. Message-ID: <4d1vkk$n86@ns.RezoNet.NET>
  9. References: <4clguu$9fs@eagle.novo.dk> <6JAN199609050601@erich.triumf.ca> <820973407snz@genesis.demon.co.uk>
  10. NNTP-Posting-Host: 204.19.230.7
  11. Mime-Version: 1.0
  12. Content-Type: Text/Plain; charset=US-ASCII
  13. X-Newsreader: WinVN 0.99.7
  14.  
  15. We all really made a meal of this string copy question.
  16.  
  17. All the tools you need for manipulating strings in 'C' are there, but 
  18. sometimes they are awkward to use, and it's sometimes best to write 
  19. your own routines to do specifically what you want.
  20.  
  21. The original question said:
  22.  
  23. >How do i do a partial stringcopy i.e. copy from a specific position in
  24. >a string and a certain numbers of bytes. I am looking for a function
  25. >like target = Stringcopy(source, startpos, length)
  26.  
  27. This seems simple on the surface, but it actually omitted more than it 
  28. said, i.e. how to handle all the pathalogical cases.
  29.  
  30. If the number of characters to be copied from the source string is 
  31. known, that implies that the terminating '\0' probably doesn't come 
  32. into it, and assuming that it's known to be overwriting _existing_ 
  33. characters in the target string, then there are no pathalogical cases, 
  34. and the solution is just a simple memcpy:
  35.  
  36.     memcpy(target + target_posn, source + source_posn, length);
  37.  
  38. [as Lawrence pointed out several times, the use of strncpy here is 
  39. probably not the best choice, even though it works perfectly well].
  40.  
  41. If you want the target to be *terminated* after the copied characters,
  42. you'd have to add the line:
  43.  
  44.     *(target + target_posn + length) = '\0';
  45.  
  46. If we don't want that though, and there is a posibility that the copied 
  47. characters "run-off" the end of the target string, it gets a little 
  48. more complicated, because again memcpy is not going to terminate the 
  49. new target string correctly, and (assuming the target has enough space 
  50. for the lengthened string) we'd have to write something like:
  51.  
  52.     target_room = strlen(target + target_posn);
  53.     memcpy(target + target_posn, source + source_posn, length);
  54.     if (target_room < length)
  55.       *(target + target_posn + length) = '\0';
  56.  
  57. Now, if there also may not be length characters in the source string at 
  58. source_posn, we have to decide what the functionality should be.  
  59. Presumably we dont want the target string to be terminated at the end 
  60. of the copied characters, so let's say we just copy as many characters 
  61. as we can:
  62.  
  63.     source_available = strlen(source + source_posn);
  64.     if (source_available < length)
  65.     length = source_available;
  66.  
  67.     target_room = strlen(target + target_posn);
  68.     memcpy(target + target_posn, source + source_posn, length);
  69.     if (target_room < length)
  70.         *(target + target_posn + length) = '\0';
  71.  
  72. It may also be necessary to check that target_posn and source_posn are 
  73. not greater than the lengths of the corresponding strings, and have a 
  74. rule as to what happens in this case - do nothing, let's say.
  75.  
  76.     source_length = strlen(source);
  77.     if (source_length > source_posn)
  78.     {
  79.       if (source_length - source_posn < length)
  80.     length = source_length - source_posn;
  81.  
  82.       target_length = strlen(target);
  83.       if (target_length >= target_posn)
  84.       {
  85.         memcpy(target + target_posn, source + source_posn, length);
  86.         if (target_posn + length > target_length)
  87.           *(target + target_posn + length) = '\0';
  88.       }
  89.     }
  90.  
  91. [there may be errors in this code, I just whacked it in, some of the 
  92. tests may be one out]
  93.  
  94. Because two strlen's and a memcpy have been required, and the logic is 
  95. quite complicated, at this point I'd give serious consideration to 
  96. writing a general purpose function which did it's own scanning of the 
  97. strings.
  98.  
  99. One case where the standard functions are particularly inefficient is 
  100. when you're doing several sequential strcat's.  Strcat has first to 
  101. scan through the whole destination string to find its end, so a 
  102. homegrown function to return the *end* of the new concatenated string 
  103. is worth considering, and are not necessarily slower than using 
  104. library functions.  At one point in the MS 'C' libraries (up to 5.1 at 
  105. least), strcmp and strstr were doing strlen's on both the strings prior 
  106. to the compare scan - I found this out when I used these functions to 
  107. repetitively scan very large file buffers - needless to say I wrote my 
  108. own routines.
  109.  
  110. ...and yes, string manipulation is much easier in BASIC, but I wouldn't 
  111. use that as a reason to program in BASIC rather than 'C'.
  112. -- 
  113. Ray Dunn (opinions are my own) | Phone: (514) 938 9050
  114. Montreal                       | Phax : (514) 938 5225
  115. ray@ultimate-tech.com          | Home : (514) 630 3749
  116.  
  117.